package com.atguigu.search.service.impl;

import com.atguigu.doc.ProductDoc;
import com.atguigu.param.ProductSearchParam;
import com.atguigu.pojo.Product;
import com.atguigu.search.service.SearchService;
import com.atguigu.utils.R;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * ClassName:SearchServiceImpl
 * Package:com.atguigu.search.impl
 * Description:
 *
 * @Author 应永豪
 * @Create 2024/4/22 10:42
 * @Version 1.0
 */
@Service
@Slf4j
public class SearchServiceImpl implements SearchService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public R search(ProductSearchParam param) {
//        1.判断关键字是否为null，如果是null的话就查询全部，不为null就添加all关键字按照字段查询
//        2.添加分页属性
//        3.ES查询
//        4.结果处理
        SearchRequest searchRequest = new SearchRequest("product");

        String search = param.getSearch();

        if (StringUtils.isEmpty(search)){
//            Null  不添加all关键字，查询全部
            searchRequest.source().query(QueryBuilders.matchAllQuery());//查询全部数据
        }else {
//            不为null,添加all关键字进行匹配
            searchRequest.source().query(QueryBuilders.matchQuery("all",search));
        }

//        进行分页数据添加
//偏移量计算：（当前页数-1）*页容量
        searchRequest.source().from((param.getCurrentPage()-1)*param.getPageSize());
        searchRequest.source().size(param.getPageSize());

        SearchResponse searchResponse =null;
        try {
            searchResponse= restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException("查询错误");
        }

        SearchHits hits = searchResponse.getHits();
        long value = hits.getTotalHits().value;//查询符合的数量
        SearchHit[] hitsHits = hits.getHits();//查询到的数据集合

        List<Product> products = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();
        for(SearchHit hitsHit : hitsHits){
            String sourceAsString = hitsHit.getSourceAsString();

            Product product =null;

            try {
                //productDoc all  -product  如果没有all的属性，会报错，jackson提供忽略没有属性的注解
                //todo:修改product的实体类，添加忽略没有属性的注解，防止报错
                product=objectMapper.readValue(sourceAsString, Product.class);
            } catch (JsonProcessingException e) {
               e.printStackTrace();
            }
            products.add(product);
        }

        R ok = R.ok(null, products, value);
        log.info("SearchServiceImpl.search执行完毕，结果为：{}",ok);
        return ok;


    }

    @Override
    public R saveProduct(Product product) throws IOException {
        IndexRequest indexRequest = new IndexRequest("product").id(product.getProductId().toString());
        ProductDoc productDoc = new ProductDoc(product);

        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(productDoc);

        indexRequest.source(json, XContentType.JSON);
        restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);

        return R.ok("数据同步成功");
    }

    @Override
    public R removeProduct(Integer productId) throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest("product").id(productId.toString());

        restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
        return R.ok("ES库的数据删除成功");
    }
}
